﻿#region Copyright & licence

// This file is part of Refix.
// 
// Refix is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
// 
// Refix is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with Refix.  If not, see <http://www.gnu.org/licenses/>.
// 
// Copyright (C) 2010-11 David Musgrove and others.

#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using NUnit.Framework;

using Refix.Core.Commands;

namespace Refix.Core.Tests.Commands
{
    [TestFixture]
    public class CommandTest
    {
        [Test]
        public void KnownCommands_All_Show_Relevant_Help_Message()
        {
            foreach (var knownCommand in Command.KnownCommands)
            {
                if (knownCommand.Key == "help") continue;
                if (knownCommand.Key == "version") continue;
                if (knownCommand.Key == "ver") continue;
                var command = new CommandWithOptions(new[] { knownCommand.Key, "-qv" });
                var builder = new StringBuilder();
                OutputWriter.Writer = new StringWriter(builder);
                bool valid = command.Command.Validate();
                if (valid)
                {
                    Console.WriteLine("Command {0} should have passed validation.", knownCommand.Key);
                }
                Assert.False(valid);
                StringAssert.Contains("Invalid combination of options", builder.ToString());
            }
        }

        [Test]
        public void KnownCommands_All_Respect_Base_Validate()
        {
            foreach (var knownCommand in Command.KnownCommands)
            {
                if (knownCommand.Key == "help") continue;
                var builder = new StringBuilder();
                OutputWriter.Writer = new StringWriter(builder);
                ((Command)Activator.CreateInstance(knownCommand.Value)).ShowHelp();
                StringAssert.Contains("rfx " + knownCommand.Key, builder.ToString(),
                                      "Help message didn't contains command.");
            }
        }

        [Test]
        public void TryParse_Empty_Queue_Returns_False_With_Error()
        {
            var builder = new StringBuilder();
            OutputWriter.Writer = new StringWriter(builder);
            Command command;
            var queue = new Queue<string>();
            Assert.False(Command.TryParse(queue, out command), "Command didn't return false for empty queue.");
            Assert.IsNotEmpty(builder.ToString(), "Command didn't write to output for empty queue.");
        }

        [Test]
        public void TryParse_Parses_Long_Form()
        {
            Command command;
            var queue = new Queue<string>();
            queue.Enqueue("visualize");
            Assert.True(Command.TryParse(queue, out command), "Command failed to parse 'visualize'.");
            Assert.IsInstanceOf(typeof(Visualize), command, "Command failed to parse 'visualize' to type Extract.");
            Assert.AreEqual(0, queue.Count, "Command failed to pop entry off queue.");
        }

        [Test]
        public void TryParse_Parses_Short_Form()
        {
            Command command;
            var queue = new Queue<string>();
            queue.Enqueue("vis");
            Assert.True(Command.TryParse(queue, out command), "Command failed to parse 'vis'.");
            Assert.IsInstanceOf(typeof(Visualize), command, "Command failed to parse 'vis' to type Extract.");
            Assert.AreEqual(0, queue.Count, "Command failed to pop entry off queue.");
        }

        [Test]
        public void TryParse_Unknown_Option_Returns_False_And_Reports_Error()
        {
            var builder = new StringBuilder();
            OutputWriter.Writer = new StringWriter(builder);
            Command command;
            var queue = new Queue<string>();
            queue.Enqueue("unknown");
            Assert.False(Command.TryParse(queue, out command),
                         "Command didn't return false for unknown Command.");
            StringAssert.Contains("unknown", builder.ToString(),
                                  "Command didn't report failure parsing unknown Command.");
        }
    }
}